package com.glink.manage.service.Impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.glink.common.contants.BaseCodeConstants;
import com.glink.common.exception.GeneralSimpleException;
import com.glink.common.util.BaseCommonUtils;
import com.glink.manage.common.Constants;
import com.glink.manage.domain.ConstructionWorkBean;
import com.glink.manage.domain.ConstructionWorkUnitRelaBean;
import com.glink.manage.domain.ParticipatingUnitBean;
import com.glink.manage.domain.PersonManageBean;
import com.glink.manage.dto.constructionwork.ConstructionWorkUnitIdDTO;
import com.glink.manage.dto.constructionwork.ConstructionWorkUnitPageDTO;
import com.glink.manage.dto.constructionwork.ConstructionWorkUnitSaveDTO;
import com.glink.manage.mapper.ConstructionWorkUnitRelaMapper;
import com.glink.manage.service.*;
import com.glink.manage.vo.participatingunit.ParticipatingUnitSimpleInfoVO;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author  qiushaoshan
 * @since 2025-01-08
 */
@Service
public class ConstructionWorkUnitRelaServiceImpl extends ServiceImpl<ConstructionWorkUnitRelaMapper, ConstructionWorkUnitRelaBean> implements ConstructionWorkUnitRelaService {

    @Autowired
    private ParticipatingUnitService participatingUnitService;
    
    @Autowired
    @Lazy
    private ConstructionWorkService constructionWorkService;
    
    @Autowired
    @Lazy
    private PersonManageService personManageService;
    
    @Autowired
    @Lazy
    private VehicleService vehicleService;
    
    /**
     * 根据施工工程ID统计参建单位个数
     *
     * @param constructionWorkObjId 施工工程ID
     * @return 数量
     */
    @Override
    public Integer countByConstructionWorkObjId(String constructionWorkObjId) {
        return this.lambdaQuery().eq(ConstructionWorkUnitRelaBean::getConstructionWorkObjId, constructionWorkObjId).count();
    }

    /**
     * 查询参建单位
     *
     * @param dto 施工工程ID
     * @return 参建单位信息
     */
    @Override
    public IPage<ParticipatingUnitSimpleInfoVO> findUnitByPage(ConstructionWorkUnitPageDTO dto) {
        IPage<ConstructionWorkUnitRelaBean> constructionWorkUnitRelaBeanIPage = new Page<>(dto.getPage(), dto.getSize());

        IPage<ConstructionWorkUnitRelaBean> workUnitRelaBeanIPage = this.lambdaQuery().eq(ConstructionWorkUnitRelaBean::getConstructionWorkObjId, dto.getConstructionWorkObjId())
                .orderByAsc(ConstructionWorkUnitRelaBean::getParticipatingUnitRole)
                .orderByDesc(ConstructionWorkUnitRelaBean::getConstructionType)
                .orderByAsc(ConstructionWorkUnitRelaBean::getCreateTime)
                .orderByAsc(ConstructionWorkUnitRelaBean::getObjId)
                .page(constructionWorkUnitRelaBeanIPage);

        IPage<ParticipatingUnitSimpleInfoVO> simpleInfoVOIPage = new Page<>(workUnitRelaBeanIPage.getCurrent(), workUnitRelaBeanIPage.getSize(), workUnitRelaBeanIPage.getTotal());
        List<ParticipatingUnitSimpleInfoVO> simpleInfoVOList = Lists.newArrayList();
        if(CollectionUtils.isNotEmpty(workUnitRelaBeanIPage.getRecords())){
            List<String> unitIdList = workUnitRelaBeanIPage.getRecords().stream().map(ConstructionWorkUnitRelaBean::getParticipatingUnitObjId).collect(Collectors.toList());

            Map<String, List<ParticipatingUnitBean>> unitMap = Maps.newHashMap();
            List<ParticipatingUnitBean> participatingUnitBeanList = participatingUnitService.lambdaQuery().in(CollectionUtils.isNotEmpty(unitIdList), ParticipatingUnitBean::getObjId, unitIdList).list();
            if(CollectionUtils.isNotEmpty(participatingUnitBeanList)){
                unitMap = participatingUnitBeanList.stream().collect(Collectors.groupingBy(ParticipatingUnitBean::getObjId));
            }

            Map<String, List<PersonManageBean>> personMap = Maps.newHashMap();
            List<PersonManageBean> personManageBeanList = personManageService.lambdaQuery().in(CollectionUtils.isNotEmpty(unitIdList), PersonManageBean::getOrgId, unitIdList).list();
            if(CollectionUtils.isNotEmpty(personManageBeanList)){
                personMap = personManageBeanList.stream().collect(Collectors.groupingBy(PersonManageBean::getObjId));
            }

            Map<String, List<ParticipatingUnitBean>> finalUnitMap = unitMap;
            Map<String, List<PersonManageBean>> finalPersonMap = personMap;
            workUnitRelaBeanIPage.getRecords().forEach(obj -> {
                ParticipatingUnitSimpleInfoVO simpleInfoVO = new ParticipatingUnitSimpleInfoVO();
                simpleInfoVO.setObjId(obj.getObjId());
                if(finalUnitMap.containsKey(obj.getParticipatingUnitObjId())){
                    simpleInfoVO.setUnitName(finalUnitMap.get(obj.getParticipatingUnitObjId()).get(0).getUnitName());
                    simpleInfoVO.setContacts(finalUnitMap.get(obj.getParticipatingUnitObjId()).get(0).getContacts());
                    simpleInfoVO.setLegalPerson(finalUnitMap.get(obj.getParticipatingUnitObjId()).get(0).getLegalPerson());
                    simpleInfoVO.setConstructionType(obj.getConstructionType());
                    simpleInfoVO.setResponsiblePersonId(obj.getResponsiblePersonId());
                    simpleInfoVO.setPhone(obj.getPhone());
                    simpleInfoVO.setParticipatingUnitRole(obj.getParticipatingUnitRole());
                }
                if (finalPersonMap.containsKey(obj.getResponsiblePersonId())){
                    simpleInfoVO.setResponsibleName(finalPersonMap.get(obj.getResponsiblePersonId()).get(0).getName());
                }
                simpleInfoVOList.add(simpleInfoVO);
            });
            simpleInfoVOIPage.setRecords(simpleInfoVOList);
        }

        return simpleInfoVOIPage;
    }

    /**
     * 保存参建单位
     *
     * @param dto 保存信息
     * @return 保存状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean saveUnit(ConstructionWorkUnitSaveDTO dto) throws GeneralSimpleException {
        
        Integer count = this.lambdaQuery().eq(ConstructionWorkUnitRelaBean::getConstructionWorkObjId, dto.getConstructionWorkObjId())
                .eq(ConstructionWorkUnitRelaBean::getParticipatingUnitObjId, dto.getParticipatingUnitObjId())
                .count();
        if(Objects.nonNull(count) && count > 0){
            ConstructionWorkBean constructionWorkBean = constructionWorkService.getById(dto.getConstructionWorkObjId());
            String constructionWorkName = "";
            if(Objects.nonNull(constructionWorkBean)){
                constructionWorkName = constructionWorkBean.getWorkName();
            }
            String unitName = participatingUnitService.findNameByObjId(dto.getParticipatingUnitObjId());
            unitName = unitName == null ? "" : unitName;
            throw new GeneralSimpleException("500005", constructionWorkName, unitName);
        }

        ConstructionWorkUnitRelaBean unitRelaBean = new ConstructionWorkUnitRelaBean();
        unitRelaBean.setObjId(BaseCommonUtils.generateUUID());
        unitRelaBean.setParticipatingUnitObjId(dto.getParticipatingUnitObjId());
        unitRelaBean.setConstructionWorkObjId(dto.getConstructionWorkObjId());
        unitRelaBean.setConstructionType(dto.getConstructionType());
        unitRelaBean.setResponsiblePersonId(dto.getResponsiblePersonId());
        unitRelaBean.setPhone(dto.getPhone());
        unitRelaBean.setParticipatingUnitRole(dto.getParticipatingUnitRole());
        return save(unitRelaBean);
    }

    /**
     * 修改工程与参建单位关联信息
     * @param dto 修改工程与参建单位关联信息
     * @return 修改状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean updateUnitRelaInfo(ConstructionWorkUnitSaveDTO dto) throws GeneralSimpleException {
        if (StringUtils.isNotEmpty(dto.getObjId())){
            ConstructionWorkUnitRelaBean workUnitRelaBean = this.getById(dto.getObjId());
            if (Objects.nonNull(workUnitRelaBean)){
                workUnitRelaBean.setConstructionType(dto.getConstructionType());
                workUnitRelaBean.setResponsiblePersonId(dto.getResponsiblePersonId());
                workUnitRelaBean.setPhone(dto.getPhone());
                workUnitRelaBean.setConstructionWorkObjId(dto.getConstructionWorkObjId());
                workUnitRelaBean.setParticipatingUnitObjId(dto.getParticipatingUnitObjId());
                workUnitRelaBean.setParticipatingUnitRole(dto.getParticipatingUnitRole());
            }
            return this.updateById(workUnitRelaBean);
        }
        return false;
    }

    /**
     * 移除参建单位
     *工程管理，移除参建单位，首先检查该参建单位下准入该工程的人的准入周期是否有过期，如果没有过期，提示“当前单位下有张三，李四，工程准入周期未失效，是否仍要移除该单位并重置上述人员的到期时间为今天”，是：则移除该单位，并重置人员的到期时间为当日日期；否，则不处理
     * @param dto 移除信息
     * @return 移除状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean delUnit(ConstructionWorkUnitIdDTO dto) throws GeneralSimpleException {
        ConstructionWorkUnitRelaBean constructionWorkUnitRelaBean = this.lambdaQuery().eq(ConstructionWorkUnitRelaBean::getObjId, dto.getObjId()).one();
        if(Objects.nonNull(constructionWorkUnitRelaBean)){
            String constructionWorkObjId = constructionWorkUnitRelaBean.getConstructionWorkObjId();
            String participatingUnitObjId = constructionWorkUnitRelaBean.getParticipatingUnitObjId();

            updateAccessCycle(constructionWorkObjId, participatingUnitObjId);
        }

        return this.lambdaUpdate().eq(ConstructionWorkUnitRelaBean::getObjId, dto.getObjId()).remove();
    }

    /**
     * 解绑工程
     * @param unitObjId 参建单位ID
     * @return 状态
     * @throws GeneralSimpleException 异常
     */
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean delUnit(String unitObjId){
        List<ConstructionWorkUnitRelaBean> constructionWorkUnitRelaBeanList = this.lambdaQuery().eq(ConstructionWorkUnitRelaBean::getParticipatingUnitObjId, unitObjId).list();
        if(CollectionUtils.isNotEmpty(constructionWorkUnitRelaBeanList)){
            List<String> relaIdList = Lists.newArrayList();
            constructionWorkUnitRelaBeanList.forEach(constructionWorkUnitRelaBean -> {
                relaIdList.add(constructionWorkUnitRelaBean.getObjId());
                String constructionWorkObjId = constructionWorkUnitRelaBean.getConstructionWorkObjId();
                String participatingUnitObjId = constructionWorkUnitRelaBean.getParticipatingUnitObjId();

                updateAccessCycle(constructionWorkObjId, participatingUnitObjId);
            });
            if(CollectionUtils.isNotEmpty(relaIdList)){
                return this.removeByIds(relaIdList);    
            }
        }
        
        return true;
    }

    /**
     * 更新准入周期
     * @param constructionWorkObjId 工程ID
     * @param participatingUnitObjId 单位ID
     */
    private void updateAccessCycle(String constructionWorkObjId, String participatingUnitObjId){
        List<String> personNameList = personManageService.findAccessPersonNameByWorkObjIdAndUnitObjId(constructionWorkObjId, participatingUnitObjId);
        if(CollectionUtils.isNotEmpty(personNameList)){
            personManageService.updateAccessCycleByWorkObjIdAndUnitObjId(constructionWorkObjId, participatingUnitObjId);
        }

        List<String> licensePlateList = vehicleService.findAccessLicensePlateByWorkObjIdAndUnitObjId(constructionWorkObjId, participatingUnitObjId);
        if(CollectionUtils.isNotEmpty(licensePlateList)){
            vehicleService.updateAccessCycleByWorkObjIdAndUnitObjId(constructionWorkObjId, participatingUnitObjId);
        }
    }

    /**
     * 根据施工工程查询关联的参建单位
     *
     * @param workIdList 施工工程ID
     * @return 参建单位ID
     */
    @Override
    public List<String> findUnitIdByWorkIdIn(List<String> workIdList) {
        List<ConstructionWorkUnitRelaBean> unitRelaBeanList = this.lambdaQuery().in(ConstructionWorkUnitRelaBean::getConstructionWorkObjId, workIdList).list();
        if(CollectionUtils.isNotEmpty(unitRelaBeanList)){
            return unitRelaBeanList.stream().map(ConstructionWorkUnitRelaBean::getParticipatingUnitObjId).distinct().collect(Collectors.toList());
        }

        return null;
    }

    /**
     * 删除参建单位关系
     * @param unitId 参建单位ID
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void delUnitByUnitId(String unitId) {
        this.lambdaUpdate().eq(ConstructionWorkUnitRelaBean::getParticipatingUnitObjId, unitId).remove();
    }

    /**
     * 校验是否可以移除
     * 工程管理，移除参建单位，首先检查该参建单位下准入该工程的人的准入周期是否有过期，如果没有过期，提示“当前单位下有张三，李四，工程准入周期未失效，是否仍要移除该单位并重置上述人员的到期时间为今天”，是：则移除该单位，并重置人员的到期时间为当日日期；否，则不处理
     * @param dto 参建单位ID
     * @return 移除状态
     */
    @Override
    public List<String> findDelUnitExistValidAccess(ConstructionWorkUnitIdDTO dto) throws GeneralSimpleException {
        ConstructionWorkUnitRelaBean constructionWorkUnitRelaBean = this.lambdaQuery().eq(ConstructionWorkUnitRelaBean::getObjId, dto.getObjId()).one();
        if(Objects.nonNull(constructionWorkUnitRelaBean)){
            String constructionWorkObjId = constructionWorkUnitRelaBean.getConstructionWorkObjId();
            String participatingUnitObjId = constructionWorkUnitRelaBean.getParticipatingUnitObjId();
            List<String> personNameList = personManageService.findAccessPersonNameByWorkObjIdAndUnitObjId(constructionWorkObjId, participatingUnitObjId);

            List<String> licensePlateList = vehicleService.findAccessLicensePlateByWorkObjIdAndUnitObjId(constructionWorkObjId, participatingUnitObjId);
            
            List<String> allName = Lists.newArrayList();
            if(CollectionUtils.isNotEmpty(personNameList)){
                allName.addAll(personNameList);
            }
            if(CollectionUtils.isNotEmpty(licensePlateList)){
                allName.addAll(licensePlateList);
            }
            
            return allName;
        }

        return Lists.newArrayList();
    }

    /**
     * 根据参建单位查询工程ID
     *
     * @param orgId 参建单位ID
     * @return 工程ID
     */
    @Override
    public List<String> findWorkIdByUnitId(String orgId) {
        List<ConstructionWorkUnitRelaBean> unitRelaBeanList = this.lambdaQuery().eq(ConstructionWorkUnitRelaBean::getParticipatingUnitObjId, orgId).list();
        if(CollectionUtils.isNotEmpty(unitRelaBeanList)){
            return unitRelaBeanList.stream().map(ConstructionWorkUnitRelaBean::getConstructionWorkObjId).distinct().collect(Collectors.toList());
        }
        return null;
    }

    /**
     * 根据单位查询监理单位所监理的工程，查询工程下的所有参建单位
     *
     * @param orgId  监理单位
     * @param workId
     * @return 参见单位
     */
    @Override
    public List<String> findParticipatingUnitObjIdBySupervisorUnit(String orgId, String workId) {
        List<ConstructionWorkUnitRelaBean> unitRelaBeanList = this.lambdaQuery()
                .eq(ConstructionWorkUnitRelaBean::getParticipatingUnitObjId, orgId)
                .eq(StringUtils.isNotBlank(workId), ConstructionWorkUnitRelaBean::getConstructionWorkObjId, workId)
                .eq(ConstructionWorkUnitRelaBean::getConstructionType, Constants.ConstructionType.supervisor)
                .list();
        if(CollectionUtils.isNotEmpty(unitRelaBeanList)){
            List<String> workIdList = unitRelaBeanList.stream().map(ConstructionWorkUnitRelaBean::getConstructionWorkObjId).distinct().collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(workIdList)){
                List<ConstructionWorkUnitRelaBean> unitRelaBeanList1 = this.lambdaQuery()
                        .in(ConstructionWorkUnitRelaBean::getConstructionWorkObjId, workIdList)
                        .list();
                if(CollectionUtils.isNotEmpty(unitRelaBeanList1)){
                    return unitRelaBeanList1.stream().map(ConstructionWorkUnitRelaBean::getParticipatingUnitObjId).distinct().collect(Collectors.toList());
                }
            }
        }
        return null;
    }

    /**
     * 移除单位负责热
     *
     * @param personId 人员ID
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void removeUnitResponsiblePersonByPersonId(String personId) {
        this.lambdaUpdate().set(ConstructionWorkUnitRelaBean::getResponsiblePersonId, "")
                .set(ConstructionWorkUnitRelaBean::getPhone, "")
                .eq(ConstructionWorkUnitRelaBean::getResponsiblePersonId, personId).update();
    }

    /**
     * 查询总包单位所管辖的参建单位列表
     *
     * @param constructionWorkIdList 工程
     * @return 参建单位
     */
    @Override
    public List<String> findGeneralContractingUnitParticipatingUnitObjIdByObjIdIn(List<String> constructionWorkIdList) {
        List<ConstructionWorkUnitRelaBean> unitRelaBeanList = this.lambdaQuery()
                .in(ConstructionWorkUnitRelaBean::getConstructionWorkObjId, constructionWorkIdList)
                .list();
        if(CollectionUtils.isNotEmpty(unitRelaBeanList)){
            return unitRelaBeanList.stream().map(ConstructionWorkUnitRelaBean::getParticipatingUnitObjId).distinct().collect(Collectors.toList());
        }
        return null;
    }

    /**
     * 根据总包单位ID查询工程ID
     *
     * @param unitObjId 总包单位ID
     * @return 工程ID
     */
    @Override
    public List<String> findWorkIdByGeneralContractingUnitId(String unitObjId) {
        List<ConstructionWorkUnitRelaBean> unitRelaBeanList = this.lambdaQuery()
                .eq(ConstructionWorkUnitRelaBean::getParticipatingUnitObjId, unitObjId)
                .eq(ConstructionWorkUnitRelaBean::getParticipatingUnitRole, BaseCodeConstants.CodeType_ParticipatingUnitRole.KEY_ParticipatingUnitRole01)
                .list();
        if(CollectionUtils.isNotEmpty(unitRelaBeanList)){
            return unitRelaBeanList.stream().map(ConstructionWorkUnitRelaBean::getConstructionWorkObjId).distinct().collect(Collectors.toList());
        }
        return null;
    }
}
